package com.googlecode.horncomb.web.spring.mvc.support;

import java.io.FileNotFoundException;
import java.util.Locale;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.view.XmlViewResolver;
import org.springframework.web.servlet.view.json.JsonView;

public class JsonViewResolver extends XmlViewResolver {
	private JsonView defaultView = new JsonView();
	private String defaultJsonViewName = "json";
	public boolean usedJsonUrlPrefix = true;
	public static final String JSON_URL_PREFIX = "json:";
	private boolean useBeanFactory = true;

	@Override
	protected void initApplicationContext() throws BeansException {
		// 初始化defaultview
		View view = loadView(this.defaultJsonViewName);
		if (view != null) {
			this.defaultView = (JsonView) view;
		} else {
			this.defaultView
					.setApplicationContext(this.getApplicationContext());
			this.defaultView.setServletContext(this.getServletContext());
			this.defaultView.setBeanName(this.defaultJsonViewName);
		}
	}

	/**
	 * Pre-initialize the factory from the XML file. Only effective if caching
	 * is enabled.
	 */
	@Override
	protected synchronized BeanFactory initFactory() throws BeansException {
		if (useBeanFactory) {
			try {
				return super.initFactory();
			} catch (BeansException be) {
				if (be.getRootCause() instanceof FileNotFoundException) {
					// 忽略配置文件没有找到的异常
					useBeanFactory = false;
					return null;
				} else {
					throw be;
				}
			}
		} else {
			return null;
		}
	}

	@Override
	protected View createView(String viewName, Locale locale) throws Exception {
		if (defaultJsonViewName.equals(viewName.trim())) {
			return this.defaultView;
		} else {
			String jsonUrl = null;
			if (!usedJsonUrlPrefix) {
				jsonUrl = viewName;
			} else if (viewName.startsWith(JSON_URL_PREFIX)) {
				// Check for special "json:" prefix.
				jsonUrl = viewName.substring(JSON_URL_PREFIX.length());
			} else {
				return null;
			}
			return super.createView(jsonUrl, locale);
		}
	}

	protected View loadView(String viewName) {
		BeanFactory factory = initFactory();
		viewName = viewName.trim();
		if (factory != null && StringUtils.hasText(viewName)) {
			try {
				return (View) factory.getBean(viewName, View.class);
			} catch (NoSuchBeanDefinitionException ex) {
				return null;
			}
		} else {
			return null;
		}

	}

	@Override
	protected View loadView(String viewName, Locale locale)
			throws BeansException {
		return loadView(viewName);
	}

	/**
	 * @param defaultJsonView
	 *            the defaultJsonView to set
	 */
	public void setDefaultView(JsonView defaultJsonView) {
		this.defaultView = defaultJsonView;
	}

	/**
	 * @param defaultJsonViewName
	 *            the defaultJsonViewName to set
	 */
	public void setDefaultJsonViewName(String defaultJsonViewName) {
		this.defaultJsonViewName = defaultJsonViewName;
	}

	/**
	 * @param usedJsonUrlPrefix
	 *            the usedJsonUrlPrefix to set
	 */
	public void setUsedJsonUrlPrefix(boolean usedJsonUrlPrefix) {
		this.usedJsonUrlPrefix = usedJsonUrlPrefix;
	}
}
